let has = {}; // vue源码里有的时候去重用的是set 有的时候用的是对象来实现的去重
let queue = [];

// nextTick的异步更新

// 这个队列是否正在等待更新
function flushSchedulerQueue() {
  for (let i = 0; i < queue.length; i++) {
    queue[i].run(); // 可以更新页面
  }
  queue = []; // [watcher1, watcher2, watcher3, ....]
  has = {};
}
// this.msg = ''  this.id = ''  this.age = '2332';
// 如果修改了数据，当前模板的更新方法是通过nextTick更新的，不是同步更新的
export function queueWatcher(watcher) {
  // 不同的组件id是不相同的
  // 同一个组件id是相同的
  // 每一个组件都有自己的独立的更新wathcer >> 不同组件的更新wwatcher的id是不会重复的
  const id = watcher.id;

  // 防止watcher重复添加
  if (has[id] == null) {
    has[id] = true; // 如果没有注册过这个watcher，就注册这个watcher到队列中，并且标记为已经注册
    queue.push(watcher); // 当前的更新watcher push进去queue里面
    nextTick(flushSchedulerQueue); // flushSchedulerQueue 调用渲染watcher
  }
}

let callbacks = []; // [flushSchedulerQueue,fn]
let pending = false;

function flushCallbacksQueue() {
  callbacks.forEach((fn) => fn());
  pending = false;
}
// this.msg = 'newMsg'
// 获取更新之后的最新dom
// this.$nextTick(() => {
//     const ref = this.$refs.inputRef
// })

export function nextTick(fn) {
  // 传入的函数不是同步执行，而是放到异步队列。
  callbacks.push(fn); // 防抖 [flushSchedulerQueue, nextTickFn]
  if (!pending) {
    // true  事件环的概念 promise mutationObserver setImmediate setTimeout
    // vue源码里面不是用setTiemout,
    setTimeout(() => {
      flushCallbacksQueue();
    }, 0);
    pending = true;
  }
}

// this.$nextTick(() => {
//   console.log('获取罪行的dom');
// })

Vue.prototye.$nextTick = nextTick
